/*
 *     This file is part of Mobile GPS Logger.
 * 
 *     Mobile GPS Logger is free software: you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License as
 *     published by the Free Software Foundation, either version 3 of the
 *     License, or (at your option) any later version.
 * 
 *     Mobile GPS Logger is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License v3 for more details.
 * 
 *     You should have received a copy of the GNU General Public License v3
 *     along with Mobile GPS Logger. If not, see <http://www.gnu.org/licenses/>.
 */

package cx.ath.skyflyer.gpslog.gps;

import cx.ath.skyflyer.gpslog.nmea.GpsFixData;
import cx.ath.skyflyer.gpslog.nmea.NmeaUtils;
import cx.ath.skyflyer.gpslog.util.M;

/**
 * A geographical position.
 * @author Ahti Legonkov
 */
public class Position {

    /**
     *
     * @param lat latitude in form of DDDMM.mmm.
     * @param north true if latitude indicates Nothern hemisphere.
     * @param lon DDDMM.mmm
     * @param east true if latitude indicated Eastern hemishpere.
     */
    public Position(String lat, boolean north, String lon, boolean east) {
        latitude = degreesToRadians(lat, north);
        longitude = degreesToRadians(lon, east);
        cosLatitude = Math.cos(latitude);
    }

    public Position(GpsFixData fix) {
        latitude = fix.getLatitude();
        longitude = fix.getLongitude();
        cosLatitude = Math.cos(latitude);
    }

    private static double degreesToRadians(String d, boolean positive) {

        double res = NmeaUtils.degreesToRadians(d);
        if (positive)
            return res;

        return -res;
    }

    public double getLatitude() {
        return latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    /**
     * Returns distance from another position p in meters.
     * @param p another position
     * @return distance from p in meters.
     */
    public double distanceFrom(Position p) {

        final double DIAMETER_OF_EARTH_M = 2.0 * 6371009.0;
        final double horizontalDistance
            = DIAMETER_OF_EARTH_M * M.asin(
                Math.sqrt(
                    M.haversin(getLatitude() - p.getLatitude())
                    + cosLatitude//Math.cos(getLatitude())
                        * p.cosLatitude//Math.cos(p.getLatitude())
                        * M.haversin(getLongitude() - p.getLongitude())
                )
            );

        return horizontalDistance;
    }

    private final double cosLatitude;
    private final double latitude;
    private final double longitude;
}
